<template>
  <div id="mountNode" style="background-color:#04144c;">
    <!-- <div id="mountNode" > -->

  </div>
</template>

<script setup>
import G6 from '@antv/g6';
import { LAYOUT_CONFIG } from 'dagre-compound';
import { onMounted, ref } from 'vue';

//图谱数据
const data = ref({
  // 点集
  // 单个点配置
  nodes: [
    {
      //最中间的节点
      id: 'node1', // String，该节点存在则必须，节点的唯一标识
      size: [100, 100],//节点大小
      //单个节点图片配置
      icon: {
        show: true,
        img: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',//节点图地址
        width: 50,
        height: 60,
      },
    },
    {
      id: 'node2', // String，该节点存在则必须，节点的唯一标识style

    },
    {
      id: 'node3', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node4', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node5', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node6', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node7', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node8', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node9', // String，该节点存在则必须，节点的唯一标识
      size: [100, 100] //节点大小

    },
    {
      id: 'node10', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node11', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node12', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node13', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node14', // String，该节点存在则必须，节点的唯一标识
    },
    {
      id: 'node15', // String，该节点存在则必须，节点的唯一标识
    },

  ],
  // 边集
  //单个边配置
  edges: [
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node2', // String，必须，目标点 id
    },
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node3', // String，必须，目标点 id
    },
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node4', // String，必须，目标点 id
    },
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node5', // String，必须，目标点 id
    },
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node6', // String，必须，目标点 id
    },
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node7', // String，必须，目标点 id
    },
    {
      source: 'node1', // String，必须，起始点 id
      target: 'node8', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node1', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node10', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node11', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node12', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node13', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node14', // String，必须，目标点 id
    },
    {
      source: 'node9', // String，必须，起始点 id
      target: 'node15', // String，必须，目标点 id
    },


  ],

})

//默认配置
const defaultConfiguration = (container) => {
  return {
    container: container, // String | HTMLElement，必须，在 Step 1 中创建的容器 id 或容器本身
    width: container.scrollWidth, // Number，必须，图的宽度
    height: container.scrollHeight || 600, // Number，必须，图的高度
    modes: {
      default: ['drag-node', 'drag-canvas'],//画布可拖拽及节点可拖拽
    },
    edgeStateStyles: {
      //点击后的边样式状态
      //edgeHighlight1和edgeHighlight2自定义取名  区分关系  样式一样
      edgeHighlight1: {
        lineWidth: 1,
        stroke: "rgb(234, 234, 234)",
        startArrow: {
          path: G6.Arrow.triangle(4, 3, 20),//三个数值分别为宽度,长度,偏移量
        },
      },
      edgeHighlight2: {
        lineWidth: 1,
        stroke: "rgb(234, 234, 234)",
        startArrow: {
          path: G6.Arrow.triangle(4, 3, 20),//三个数值分别为宽度,长度,偏移量
        },
      }

    },
    nodeStateStyles: {
      // 点击后节点样式状态
      //Highlight1和Highlight2自定义取名  区分关系  样式一样
      Highlight1: {
        lineWidth: 4,
        stroke: "rgb(234, 234, 234)",
        fillOpacity: 1,
        strokeOpacity: 1
      },
      Highlight2: {
        lineWidth: 4,
        stroke: "rgb(234, 234, 234)",
        fillOpacity: 1,
        strokeOpacity: 1
      },

    },
    layout: {
      type: 'force',
      animate: true, // 设置为 false 可关闭布局动画
      preventOverlap: true,
      linkDistance: 200,//边长度
      edgeStrength: 0.9,
      nodeSize: 25,
      nodeSpacing: (d) => {
        if (d.id === 'node1' || d.id === 'node9') {//不同节点的斥力
          return 100;
        }
        return 25;
      },
    },
    fitCenter: true,
    defaultNode: {
      type: 'circle',
      size: [25, 25],
      icon: {
        show: true,
        img: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',//节点图地址
        width: 25,
        height: 25,
      },
      style: {
        fill: '#334561',
        stroke: '#4971b4',
        fillOpacity: 0.5,
        strokeOpacity: 0.5
      }

    },
    //全局默认边配置
    defaultEdge: {
      type: 'line',//边类型
      style: {
        stroke: 'skyblue',
        startArrow: false,
        lineWidth: 0.5,
      },
      triangle: 5
    },
  }




}
//重置画布缩放
const resetZoom = (graph) => {
  graph.on('canvas:click', (evt) => {
    //缩放
    graph.zoomTo(1, { x: 200, y: 200 }, true, {
      duration: 100,
    });

  })
}
//缩放
const setZoom=(graph,item)=>{
 //缩放
 graph.focusItem(item, true, {
      easing: 'easeCubic',
      duration: 400,
    });
    graph.zoomTo(1.5, { x: item._cfg.bboxCache.x, y: item._cfg.bboxCache.y }, true, {
      duration: 100,

    });
}

//节点点击显示效果逻辑
const nodesShow=(graph,item)=>{
   //节点相关
   if (graph.findAllByState('node', 'Highlight1').length === 0) {
      //取消所有高2状态
      graph.findAllByState('node', 'Highlight2').forEach(i => {
        graph.setItemState(i, 'Highlight2', false);
      })

      //设置所有高1状态
      graph.setItemState(item, 'Highlight1', true);
      graph.getNeighbors(item, 'target').forEach(ITEM => {
        graph.setItemState(ITEM, 'Highlight1', true);
      })


    } else if (graph.findAllByState('node', 'Highlight2').length === 0) {
      //取消所有高1状态
      graph.findAllByState('node', 'Highlight1').forEach(i => {
        graph.setItemState(i, 'Highlight1', false);
      })

      //设置所有高2状态

      graph.setItemState(item, 'Highlight2', true);
      graph.getNeighbors(item, 'target').forEach(ITEM => {
        graph.setItemState(ITEM, 'Highlight2', true);
      })

    }

}

//点击节点后边显示逻辑

const edgeShow=(graph,item)=>{
      //边相关
      if (graph.findAllByState('edge', 'edgeHighlight1').length === 0) {
      //取消所有高2状态
      graph.findAllByState('edge', 'edgeHighlight2').forEach(i => {
        graph.setItemState(i, 'edgeHighlight2', false);
        //配置边的描述及样式
        graph.updateItem(i, {
          label: '',
          labelCfg: {

          }
        });

      })
      //设置所有高1状态
      graph.findAll('edge', (edge) => {
        return edge._cfg.model.source === item._cfg.id
      }).forEach(i => {
        graph.setItemState(i, 'edgeHighlight1', true);
        //配置边的描述及样式
        graph.updateItem(i, {
          label: '关系',
          labelCfg: {
            fill: '#8cc6ff',
            autoRotate: true,//是否跟边旋转
            style: {
              fontSize: 8,//字体大小
              background: {
                fill: '#8cc6ff',
                padding: [2, 2, 2, 2],
                radius: 5,
              }
            },
          }
        });

      })

    } else if (graph.findAllByState('edge', 'edgeHighlight2').length === 0) {
      //取消所有高1状态
      graph.findAllByState('edge', 'edgeHighlight1').forEach(i => {
        graph.setItemState(i, 'edgeHighlight1', false);
        graph.updateItem(i, {
          label: '',
          labelCfg: {

          }
        });
      })


      //设置所有高2状态
      graph.findAll('edge', (edge) => {
        return edge._cfg.model.source === item._cfg.id
      }).forEach(i => {
        graph.setItemState(i, 'edgeHighlight2', true);
        //更新配置边的描述及样式
        graph.updateItem(i, {
          label: '关系',
          labelCfg: {
            fill: '#8cc6ff',
            autoRotate: true,//是否跟边旋转
            style: {
              fontSize: 8,//字体大小
              background: {
                fill: '#8cc6ff',
                padding: [2, 2, 2, 2],
                radius: 5,
              }
            },
          }
        });
      })

    }
}


onMounted(() => {
  const container = document.getElementById('mountNode');
  const graph = new G6.Graph(defaultConfiguration(container));
  graph.data(data.value); // 读取data数据源到图上
  graph.render(); // 渲染图
  resetZoom(graph)
  //默认高亮节点  
    //节点
    nodesShow(graph,graph.getNodes()[0])
    //边
    edgeShow(graph,graph.getNodes()[0])
   
  // 为图上的所有节点绑定点击监听
  graph.on('node:click', (evt) => {
    const item = evt.item; // 被操作的节点 item
    const target = evt.target; // 被操作的具体图形
    //缩放
    setZoom(graph,item)
    //点击后节点样式逻辑
    //节点
    nodesShow(graph,item)
    //边
    edgeShow(graph,item)

  });




  //拖拽移动相关不用管
  function refreshDragedNodePosition(e) {
    const model = e.item.get('model');
    model.fx = e.x;
    model.fy = e.y;
  }
  graph.on('node:dragstart', (e) => {
    graph.layout();
    refreshDragedNodePosition(e);
  });
  graph.on('node:drag', (e) => {
    refreshDragedNodePosition(e);
  });

  //不用管
  if (typeof window !== 'undefined')
    window.onresize = () => {
      if (!graph || graph.get('destroyed')) return;
      if (!container || !container.scrollWidth || !container.scrollHeight) return;
      graph.changeSize(container.scrollWidth, container.scrollHeight);
    };




})





</script>

<style></style>